#include "ai_image.h"
#include "esp_log.h"
#include "esp_http_client.h"
#include "mbedtls/base64.h"
#include "cJSON.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_crt_bundle.h"
#include "i2s_audio.h"
#include "ai_image.h"

static const char *TAG = "AI_IMAGE";

// 千问API配置
#define QIANWEN_URL "https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions"
#define API_KEY "sk-f954de51de78401684df0e895b15e567"

// AI响应回调函数
static ai_image_callback_t ai_callback = NULL;

// 用于累计音频数据的缓冲区
static char *audio_buffer = NULL;
static size_t audio_buffer_len = 0;
static const size_t MAX_AUDIO_BUFFER_SIZE = 5 * 1024 * 1024; // 5MB最大音频缓冲区

// 解码后的音频数据缓冲区
static uint8_t *decoded_audio_buffer = NULL;
static size_t decoded_audio_len = 0;
#define MAX_DECODED_AUDIO_SIZE (10 * 1024 * 1024) // 10MB最大解码后音频缓冲区

// Base64编码函数
static char* base64_encode(const uint8_t* data, size_t input_length, size_t* output_length) {
    size_t b64_len = ((input_length + 2) / 3) * 4 + 4; // 增加4字节安全余量
    // 分配内存（包含终止符）
    unsigned char* b64_data = malloc(b64_len + 1);
    if (!b64_data) {
        ESP_LOGE(TAG, "Base64内存分配失败");
        return NULL;
    }
    // 执行Base64编码
    int ret = mbedtls_base64_encode(
        b64_data, b64_len, output_length,
        data, input_length
    );

    if (ret != 0) {
        ESP_LOGE(TAG, "Base64编码失败，错误码: %d", ret);
        free(b64_data);
        return NULL;
    }

    // 添加终止符
    b64_data[*output_length] = '\0';
    
    return (char*)b64_data;
}

// Base64解码函数 - 版本3新增
static int base64_decode(const char* encoded_data, size_t encoded_length, uint8_t** decoded_data, size_t* decoded_length) {
    // 计算解码所需的最大缓冲区大小
    *decoded_length = encoded_length / 4 * 3 + 1; // 最大可能的解码后长度
    
    // 检查是否超过最大允许大小
    if (*decoded_length > MAX_DECODED_AUDIO_SIZE) {
        ESP_LOGE(TAG, "解码后音频数据超过最大允许大小");
        return -1;
    }
    
    uint8_t* temp_buffer = malloc(*decoded_length);
    if (!temp_buffer) {
        ESP_LOGE(TAG, "Base64解码缓冲区分配失败");
        return -1;
    }

    // 使用mbedtls_base64_decode进行解码
    int ret = mbedtls_base64_decode(
        temp_buffer, *decoded_length, decoded_length,
        (const unsigned char*)encoded_data, encoded_length
    );

    if (ret != 0) {
        ESP_LOGE(TAG, "Base64解码失败，错误码: %d", ret);
        free(temp_buffer);
        return -1;
    }

    // 调整缓冲区大小以匹配实际解码长度
    uint8_t* new_buffer = realloc(temp_buffer, *decoded_length);
    if (new_buffer) {
        // 如果realloc成功，更新指针
        *decoded_data = new_buffer;
    } else {
        // 如果realloc失败，使用原始缓冲区
        *decoded_data = temp_buffer;
    }

    ESP_LOGI(TAG, "Base64解码成功，编码长度: %zu字节，解码长度: %zu字节", 
             encoded_length, *decoded_length);
    return 0;
}


// 打印音频数据预览 - 版本3新增
static void print_audio_preview(const uint8_t* data, size_t len) {
    if (data == NULL || len == 0) {
        ESP_LOGI(TAG, "没有音频数据可打印预览");
        return;
    }
    
    char preview[2 * len + 1];
    for (size_t i = 0; i < len; i++) {
        snprintf(preview + i * 2, 3, "%02x", data[i]);
    }
    preview[2 * len] = '\0';
    
    ESP_LOGI(TAG, "音频数据前%zu字节预览: %s", len, preview);
}

// HTTP事件处理程序 - 支持流式响应
static esp_err_t http_event_handler(esp_http_client_event_t *evt) {
    static int response_count = 0;
    static char text_response[2048] = {0};
    static size_t text_len = 0;
    static char *stream_buffer = NULL;  // 用于累积流式响应数据
    static size_t stream_buffer_len = 0;
    static const size_t MAX_STREAM_BUFFER_SIZE = 1024 * 1024; // 1MB最大流缓冲区

    switch (evt->event_id) {
        case HTTP_EVENT_ON_DATA:
            // 仅在接收到前5个数据块时打印日志，避免日志过长
            if (response_count < 5) {
                ESP_LOGI(TAG, "HTTP_EVENT_ON_DATA, 接收到数据长度=%d", evt->data_len);
                
                // 打印前16个字节的内容，用于调试格式
                if (evt->data_len > 0) {
                    char preview[33] = {0}; // 16字节的十六进制表示需要32个字符+结束符
                    for (int i = 0; i < 16 && i < evt->data_len; i++) {
                        snprintf(preview + i * 2, 3, "%02x", ((uint8_t*)evt->data)[i]);
                    }
                    ESP_LOGI(TAG, "数据前16字节: %s", preview);
                }
                response_count++;
            } else if (response_count == 5) {
                ESP_LOGI(TAG, "后续数据块不再详细打印...");
                response_count++;
            }
            
            // 累积流式响应数据
            if (evt->data_len > 0 && evt->data != NULL) {
                // 扩展流缓冲区
                if (stream_buffer == NULL) {
                    stream_buffer = malloc(evt->data_len + 1);
                    if (stream_buffer) {
                        memcpy(stream_buffer, evt->data, evt->data_len);
                        stream_buffer[evt->data_len] = '\0';
                        stream_buffer_len = evt->data_len;
                    } else {
                        ESP_LOGE(TAG, "流缓冲区分配失败");
                    }
                } else {
                    if (stream_buffer_len + evt->data_len < MAX_STREAM_BUFFER_SIZE) {
                        char *new_buffer = realloc(stream_buffer, stream_buffer_len + evt->data_len + 1);
                        if (new_buffer) {
                            stream_buffer = new_buffer;
                            memcpy(stream_buffer + stream_buffer_len, evt->data, evt->data_len);
                            stream_buffer[stream_buffer_len + evt->data_len] = '\0';
                            stream_buffer_len += evt->data_len;
                        } else {
                            ESP_LOGE(TAG, "流缓冲区扩展失败");
                        }
                    } else {
                        ESP_LOGE(TAG, "流数据超过最大缓冲区大小");
                    }
                }
                
                // 尝试解析累积的流数据
                if (stream_buffer) {
                    char *remaining_data = stream_buffer;
                    char *line_start = remaining_data;
                    char *line_end;
                    
                    // 逐行处理数据
                    while ((line_end = strstr(line_start, "\n")) != NULL) {
                        *line_end = '\0'; // 临时终止符
                        
                        // 处理这一行数据
                        char *data_str = line_start;
                        
                        // 跳过空行
                        if (strlen(data_str) == 0) {
                            line_start = line_end + 1;
                            continue;
                        }
                        
                        // 检查是否包含"data: "标记
                        if (strstr(data_str, "data: ") != NULL) {
                            // 提取JSON部分
                            char *json_start = strstr(data_str, "data: ");
                            if (json_start) {
                                json_start += 6; // 跳过 "data: "
                                
                                // 尝试解析JSON
                                cJSON *root = cJSON_Parse(json_start);
                                if (root != NULL) {
                                    ESP_LOGD(TAG, "成功解析JSON数据块");
                                    
                                    cJSON *choices = cJSON_GetObjectItem(root, "choices");
                                    if (choices != NULL && cJSON_IsArray(choices) && cJSON_GetArraySize(choices) > 0) {
                                        cJSON *choice = cJSON_GetArrayItem(choices, 0);
                                        if (choice != NULL) {
                                            cJSON *delta = cJSON_GetObjectItem(choice, "delta");
                                            if (delta != NULL) {
                                                // 处理文本响应
                                                cJSON *content = cJSON_GetObjectItem(delta, "content");
                                                if (content != NULL && cJSON_IsString(content) && strlen(content->valuestring) > 0) {
                                                    // 累计文本响应
                                                    size_t content_len = strlen(content->valuestring);
                                                    if (text_len + content_len < sizeof(text_response) - 1) {
                                                        strncat(text_response, content->valuestring, sizeof(text_response) - text_len - 1);
                                                        text_len += content_len;
                                                    }
                                                }
                                                
                                                // 处理音频响应
                                                cJSON *audio = cJSON_GetObjectItem(delta, "audio");
                                                if (audio != NULL) {
                                                    ESP_LOGD(TAG, "在响应中发现音频字段");
                                                    cJSON *audio_data = cJSON_GetObjectItem(audio, "data");
                                                    if (audio_data != NULL && cJSON_IsString(audio_data)) {
                                                        size_t audio_data_len = strlen(audio_data->valuestring);
                                                        ESP_LOGI(TAG, "接收到音频数据片段，长度: %zu字节", audio_data_len);
                                                         
                                                        // 分配或扩展音频缓冲区
                                                        if (audio_buffer == NULL) {
                                                            audio_buffer = malloc(audio_data_len + 1);
                                                            if (audio_buffer) {
                                                                strcpy(audio_buffer, audio_data->valuestring);
                                                                audio_buffer_len = audio_data_len;
                                                            } else {
                                                                ESP_LOGE(TAG, "音频缓冲区分配失败");
                                                            }
                                                        } else {
                                                            if (audio_buffer_len + audio_data_len < MAX_AUDIO_BUFFER_SIZE) {
                                                                char *new_buffer = realloc(audio_buffer, audio_buffer_len + audio_data_len + 1);
                                                                if (new_buffer) {
                                                                    audio_buffer = new_buffer;
                                                                    strcpy(audio_buffer + audio_buffer_len, audio_data->valuestring);
                                                                    audio_buffer_len += audio_data_len;
                                                                    ESP_LOGD(TAG, "扩展音频缓冲区，新大小: %zu字节", audio_buffer_len);
                                                                } else {
                                                                    ESP_LOGE(TAG, "音频缓冲区扩展失败");
                                                                }
                                                            } else {
                                                                ESP_LOGE(TAG, "音频数据超过最大缓冲区大小");
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                    cJSON_Delete(root);
                                } else {
                                    // JSON解析失败时，记录但继续处理，因为可能是不完整的JSON
                                    ESP_LOGD(TAG, "JSON解析失败(可能是不完整的数据): %s", json_start);
                                }
                            }
                        }
                        
                        // 移动到下一行
                        line_start = line_end + 1;
                    }
                    
                    // 处理剩余的数据（不完整的行）
                    size_t remaining_len = strlen(line_start);
                    if (remaining_len > 0) {
                        // 重新分配缓冲区，只保留剩余数据
                        char *new_buffer = malloc(remaining_len + 1);
                        if (new_buffer) {
                            strcpy(new_buffer, line_start);
                            free(stream_buffer);
                            stream_buffer = new_buffer;
                            stream_buffer_len = remaining_len;
                        }
                    } else {
                        // 没有剩余数据，释放缓冲区
                        free(stream_buffer);
                        stream_buffer = NULL;
                        stream_buffer_len = 0;
                    }
                }
            }
            break;
            
        case HTTP_EVENT_ON_FINISH:
            ESP_LOGI(TAG, "HTTP_EVENT_ON_FINISH");
            
            // 处理完整的响应
            if (text_len > 0) {
                ESP_LOGI(TAG, "AI文本响应: %s", text_response);
                if (ai_callback != NULL) {
                    ai_callback(text_response);
                }
                // 清空文本缓冲区
                memset(text_response, 0, sizeof(text_response));
                text_len = 0;
            }
            
            // 处理音频数据
            if (audio_buffer != NULL && audio_buffer_len > 0) {
                ESP_LOGI(TAG, "接收到音频数据，长度: %zu字节", audio_buffer_len);
                
                // 释放之前可能存在的解码音频数据
                if (decoded_audio_buffer != NULL) {
                    free(decoded_audio_buffer);
                    decoded_audio_buffer = NULL;
                    decoded_audio_len = 0;
                }
                
                // 执行Base64解码
                int decode_result = base64_decode(
                    audio_buffer, audio_buffer_len,
                    &decoded_audio_buffer, &decoded_audio_len
                );
                
                // 在HTTP_EVENT_ON_FINISH事件中的音频处理部分
                if (decode_result == 0) {
                    ESP_LOGI(TAG, "音频数据解码成功，解码后长度: %zu字节", decoded_audio_len);
                    
                    // 打印解码后音频数据前16字节
                    size_t preview_len = (decoded_audio_len < 16) ? decoded_audio_len : 16;
                    print_audio_preview(decoded_audio_buffer, preview_len);
                    
                    // 直接播放PCM音频数据，跳过WAV格式验证
                    ESP_LOGI(TAG, "开始播放PCM音频数据");
                    size_t bytes_written = 0;
                    esp_err_t ret = i2s_audio_write(
                        decoded_audio_buffer, 
                        decoded_audio_len, 
                        &bytes_written, 
                        portMAX_DELAY  // 最大超时时间
                    );
                    
                    if (ret == ESP_OK) {
                        ESP_LOGI(TAG, "PCM音频播放完成，实际写入: %zu字节", bytes_written);
                        // 通知回调函数音频播放完成
                        if (ai_callback != NULL) {
                            char audio_ready_msg[64];
                            snprintf(audio_ready_msg, sizeof(audio_ready_msg), 
                                     "音频播放完成，大小: %zu字节", decoded_audio_len);
                            ai_callback(audio_ready_msg);
                        }
                    } else {
                        ESP_LOGE(TAG, "PCM音频播放失败: %s", esp_err_to_name(ret));
                    }
                    
                    // 播放完成后释放解码的音频数据
                    free_decoded_audio_data();
                } else {
                    ESP_LOGE(TAG, "音频数据解码失败");
                }
                
                // 释放Base64编码的音频缓冲区
                free(audio_buffer);
                audio_buffer = NULL;
                audio_buffer_len = 0;
            } else {
                ESP_LOGI(TAG, "未接收到音频数据或音频数据为空");
            }
            
            // 释放流缓冲区
            if (stream_buffer != NULL) {
                free(stream_buffer);
                stream_buffer = NULL;
                stream_buffer_len = 0;
            }
            
            // 重置响应计数器
            response_count = 0;
            break;
        
        case HTTP_EVENT_ERROR:
            ESP_LOGI(TAG, "HTTP_EVENT_ERROR");
            
            // 清理资源
            if (audio_buffer != NULL) {
                free(audio_buffer);
                audio_buffer = NULL;
                audio_buffer_len = 0;
            }
            
            // 清理解码后的音频缓冲区
            free_decoded_audio_data();
            
            // 释放流缓冲区
            if (stream_buffer != NULL) {
                free(stream_buffer);
                stream_buffer = NULL;
                stream_buffer_len = 0;
            }
            
            if (ai_callback != NULL) {
                ai_callback("AI图像分析请求失败");
            }
            
            // 重置响应计数器
            response_count = 0;
            break;
            
        default:
            break;
    }
    return ESP_OK;
}

// 构建并发送请求
static void build_and_send_request(cJSON *messages) {
    if (messages == NULL) {
        ESP_LOGE(TAG, "无效的消息对象");
        return;
    }
    
    // 构建请求JSON
    cJSON *root = cJSON_CreateObject();
    cJSON_AddStringToObject(root, "model", "qwen-omni-turbo"); // 使用Qwen-Omni模型
    
    // 设置输出模态为文本+音频
    cJSON *modalities = cJSON_CreateArray();
    cJSON_AddItemToArray(modalities, cJSON_CreateString("text"));
    cJSON_AddItemToArray(modalities, cJSON_CreateString("audio"));
    cJSON_AddItemToObject(root, "modalities", modalities);
    
    // 设置音频参数 - 使用开源版支持的音色Ethan
    cJSON *audio = cJSON_CreateObject();
    cJSON_AddStringToObject(audio, "voice", "Ethan");
    cJSON_AddStringToObject(audio, "format", "wav");
    cJSON_AddItemToObject(root, "audio", audio);
    
    // 启用流式输出
    cJSON_AddBoolToObject(root, "stream", true);
    
    // 设置stream_options
    cJSON *stream_options = cJSON_CreateObject();
    cJSON_AddBoolToObject(stream_options, "include_usage", true);
    cJSON_AddItemToObject(root, "stream_options", stream_options);
    
    // 添加消息数组
    cJSON_AddItemToObject(root, "messages", messages);
    
    // 生成请求体字符串
    char *request_body = cJSON_PrintUnformatted(root);
    ESP_LOGI(TAG, "请求体大小: %d", strlen(request_body));
    
    // 配置HTTP客户端
    esp_http_client_config_t config = {
        .url = QIANWEN_URL,
        .event_handler = http_event_handler,
        .method = HTTP_METHOD_POST,
        .timeout_ms = 15000,
        .crt_bundle_attach = esp_crt_bundle_attach,
        .cert_pem = NULL,
    };
    
    esp_http_client_handle_t client = esp_http_client_init(&config);
    
    // 设置请求头
    esp_http_client_set_header(client, "Content-Type", "application/json");
    char auth_header[128];
    snprintf(auth_header, sizeof(auth_header), "Bearer %s", API_KEY);
    esp_http_client_set_header(client, "Authorization", auth_header);
    
    // 设置请求体
    esp_http_client_set_post_field(client, request_body, strlen(request_body));
    
    // 发送请求
    esp_err_t err = esp_http_client_perform(client);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "HTTP请求失败: %s", esp_err_to_name(err));
        
        char error_msg[128];
        snprintf(error_msg, sizeof(error_msg), "HTTP请求失败: %s", esp_err_to_name(err));
        
        if (ai_callback != NULL) {
            ai_callback(error_msg);
        }
    }
    
    // 清理资源
    esp_http_client_cleanup(client);
    cJSON_Delete(root);
    free(request_body);
}

// 发送图像到AI进行分析
void send_image_to_ai(camera_fb_t *fb) {
    if (fb == NULL) {
        ESP_LOGE(TAG, "无效的帧缓冲区");
        if (ai_callback != NULL) {
            ai_callback("获取图像失败");
        }
        return;
    }
    
    // 将图像转换为Base64
    size_t b64_len;
    char* b64_data = base64_encode(fb->buf, fb->len, &b64_len);
    if (b64_data == NULL) {
        ESP_LOGE(TAG, "Base64编码失败");
        if (ai_callback != NULL) {
            ai_callback("图像编码失败");
        }
        return;
    }
    
    // 构建消息数组
    cJSON *messages = cJSON_CreateArray();
    cJSON *msg = cJSON_CreateObject();
    cJSON_AddStringToObject(msg, "role", "user");
    
    // 创建content数组，用于包含文本和图像数据
    cJSON *content_array = cJSON_CreateArray();
    
    // 创建图像部分
    cJSON *image_item = cJSON_CreateObject();
    cJSON_AddStringToObject(image_item, "type", "image_url");
    cJSON *image_url_obj = cJSON_CreateObject();
    
    // 构建Data URL: data:image/jpeg;base64,<base64_data>
    size_t data_url_len = strlen("data:image/jpeg;base64,") + strlen(b64_data) + 1;
    char *data_url = malloc(data_url_len);
    if (data_url == NULL) {
        ESP_LOGE(TAG, "Data URL内存分配失败");
        cJSON_Delete(messages);
        free(b64_data);
        if (ai_callback != NULL) {
            ai_callback("内存分配失败");
        }
        return;
    }
    strcpy(data_url, "data:image/jpeg;base64,");
    strcat(data_url, b64_data);
    
    cJSON_AddStringToObject(image_url_obj, "url", data_url);
    cJSON_AddItemToObject(image_item, "image_url", image_url_obj);
    cJSON_AddItemToArray(content_array, image_item);
    
    // 创建文本部分
    cJSON *text_item = cJSON_CreateObject();
    cJSON_AddStringToObject(text_item, "type", "text");
    cJSON_AddStringToObject(text_item, "text", "请分析以下图片并详细描述其内容");
    cJSON_AddItemToArray(content_array, text_item);
    
    // 将content数组添加到消息
    cJSON_AddItemToObject(msg, "content", content_array);
    
    // 将消息添加到消息数组
    cJSON_AddItemToArray(messages, msg);
    
    // 释放Data URL内存
    free(data_url);
    
    // 构建并发送请求
    build_and_send_request(messages);
    
    // 清理资源
    free(b64_data);
}

// 设置AI响应回调函数
void set_ai_image_callback(ai_image_callback_t callback) {
    ai_callback = callback;
}

// 获取解码后的音频数据 
uint8_t* get_decoded_audio_data(size_t* data_len) {
    if (data_len != NULL) {
        *data_len = decoded_audio_len;
    }
    return decoded_audio_buffer;
}

// 释放解码后的音频数据 
void free_decoded_audio_data(void) {
    if (decoded_audio_buffer != NULL) {
        free(decoded_audio_buffer);
        decoded_audio_buffer = NULL;
        decoded_audio_len = 0;
        ESP_LOGI(TAG, "解码后的音频数据已释放");
    }
}

// 初始化AI图像处理功能
void ai_image_init(void) {
    ESP_LOGI(TAG, "AI图像处理功能初始化完成");
}